home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Packet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  26.4 KB  |  1,239 lines

  1. /*
  2. **    Packet.c
  3. **
  4. **    Support routines for the `packet window'
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #ifndef _GLOBAL_H
  11. #include "Global.h"
  12. #endif
  13.  
  14.     /* A custom message structure. */
  15.  
  16. struct PacketMessage
  17. {
  18.     struct Message     VanillaMessage;
  19.     LONG         Line;
  20. };
  21.  
  22.     /* Some private data required to handle both the window,
  23.      * the editing functions and the command history buffer.
  24.      */
  25.  
  26. STATIC STRPTR             PacketContents;
  27.  
  28. STATIC struct Process        *PacketProcess;
  29. STATIC struct SignalSemaphore     PacketSemaphore;
  30. STATIC struct MsgPort        *PacketPort;
  31.  
  32. STATIC LONG             PacketLine;
  33. STATIC LONG             PacketCount;
  34. STATIC STRPTR             PacketString    = NULL;
  35. STATIC LONG             PacketX    = -1,
  36.                  PacketY    = -1,
  37.                  PacketWidth    = -1,
  38.                  PacketHeight    = -1;
  39.  
  40. STATIC BOOLEAN             HasList    = FALSE,
  41.                  Echo        = -1;
  42.                  PacketSignal    = -1;
  43.  
  44.     /* Gadget IDs */
  45.  
  46. enum    {    GAD_STRING, GAD_LIST };
  47.  
  48.     /* The menu to attach to the packet window. */
  49.  
  50. enum    {    MEN_LOADHISTORY=1,MEN_SAVEHISTORY,MEN_CLEARHISTORY,MEN_OTHERWINDOW,
  51.         MEN_TOGGLE_ECHO,MEN_QUITPANEL
  52.     };
  53.  
  54. STATIC VOID __stdargs
  55. PacketDestructor(struct MsgItem *Item)
  56. {
  57.     Signal(PacketProcess,1L << PacketSignal);
  58. }
  59.  
  60. STATIC VOID
  61. PacketSerWrite(APTR Data,LONG Size)
  62. {
  63.     struct DataMsg Msg;
  64.  
  65.     InitMsgItem(&Msg,PacketDestructor);
  66.  
  67.     Msg . Type = DATAMSGTYPE_WRITE;
  68.     Msg . Data = Data;
  69.     Msg . Size = Size;
  70.  
  71.     Forbid();
  72.  
  73.     ClrSignal(1L << PacketSignal);
  74.  
  75.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  76.  
  77.     Wait(1L << PacketSignal);
  78.  
  79.     Permit();
  80. }
  81.  
  82. STATIC VOID
  83. PacketSerialCommand(STRPTR String)
  84. {
  85.     struct DataMsg Msg;
  86.  
  87.     InitMsgItem(&Msg,PacketDestructor);
  88.  
  89.     if(Echo)
  90.         Msg . Type = DATAMSGTYPE_SERIALCOMMAND;
  91.     else
  92.         Msg . Type = DATAMSGTYPE_SERIALCOMMANDNOECHO;
  93.  
  94.     Msg . Data = String;
  95.  
  96.     Forbid();
  97.  
  98.     ClrSignal(1L << PacketSignal);
  99.  
  100.     PutMsgItem(SpecialQueue,(struct MsgItem *)&Msg);
  101.  
  102.     Wait(1L << PacketSignal);
  103.  
  104.     Permit();
  105. }
  106.  
  107.     /* SendPacketMsg(LONG Line):
  108.      *
  109.      *    Tell the main process to display a certain line.
  110.      */
  111.  
  112. STATIC VOID
  113. SendPacketMsg(LONG Line)
  114. {
  115.     struct PacketMessage *Msg;
  116.  
  117.     if(Msg = (struct PacketMessage *)AllocVecPooled(sizeof(struct PacketMessage),MEMF_PUBLIC | MEMF_CLEAR))
  118.     {
  119.         Msg -> VanillaMessage . mn_Length    = sizeof(struct PacketMessage);
  120.         Msg -> Line                = Line;
  121.  
  122.         PutMsg(PacketPort,Msg);
  123.     }
  124. }
  125.  
  126.     /* PacketKey(struct Hook *Hook,struct SGWork *Work,ULONG *Msg):
  127.      *
  128.      *    This is a string gadget editing call back routine
  129.      *    (a so-called `hook') which is to perform all the
  130.      *    line editing and command history actions supported
  131.      *    by the packet window.
  132.      */
  133.  
  134. STATIC ULONG __saveds __asm
  135. PacketKey(REG(a0) struct Hook *Hook,REG(a1) ULONG *Msg,REG(a2) struct SGWork *Work)
  136. {
  137.         /* Someone activated the string gadget and
  138.          * hit a key.
  139.          */
  140.  
  141.     if(*Msg == SGH_KEY)
  142.     {
  143.             /* Right-Amiga-key was pressed, release the
  144.              * string gadget so user may select a menu
  145.              * item.
  146.              */
  147.  
  148.         if((Work -> IEvent -> ie_Qualifier & AMIGARIGHT) && Work -> IEvent -> ie_Code < 96)
  149.         {
  150.             if(!(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) && (Work -> IEvent -> ie_Code == KEYCODE_X || Work -> IEvent -> ie_Code == KEYCODE_Q))
  151.                 return(TRUE);
  152.             else
  153.             {
  154.                 Work -> Actions = (Work -> Actions & ~(SGA_USE | SGA_BEEP)) | SGA_END | SGA_REUSE;
  155.                 Work -> Code = '\t';
  156.  
  157.                 CommandWindow = Work -> GadgetInfo -> gi_Window;
  158.                 CommandGadget = Work -> Gadget;
  159.             }
  160.         }
  161.  
  162.         if(Work -> IEvent -> ie_Code >= F01_CODE && Work -> IEvent -> ie_Code <= F10_CODE)
  163.         {
  164.             STATIC UBYTE OtherBuffer[2048];
  165.  
  166.             STRPTR    String;
  167.             LONG    Len,Index = Work -> IEvent -> ie_Code - F01_CODE;
  168.  
  169.             Forbid();
  170.  
  171.             if(Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL)
  172.                 String = MacroKeys -> Keys[3][Index];
  173.             else
  174.             {
  175.                 if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT))
  176.                     String = MacroKeys -> Keys[2][Index];
  177.                 else
  178.                 {
  179.                     if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  180.                         String = MacroKeys -> Keys[1][Index];
  181.                     else
  182.                         String = MacroKeys -> Keys[0][Index];
  183.                 }
  184.             }
  185.  
  186.             if(Len = strlen(String))
  187.             {
  188.                 if(Work -> BufferPos)
  189.                     CopyMem(Work -> PrevBuffer,OtherBuffer,Work -> BufferPos);
  190.  
  191.                 OtherBuffer[Work -> BufferPos] = 0;
  192.  
  193.                 strcat(OtherBuffer,String);
  194.  
  195.                 strcat(OtherBuffer,&Work -> PrevBuffer[Work -> BufferPos]);
  196.  
  197.                 if(strlen(OtherBuffer) > 1023)
  198.                     OtherBuffer[1023] = 0;
  199.  
  200.                 strcpy(Work -> WorkBuffer,OtherBuffer);
  201.  
  202.                 if(Work -> StringInfo -> UndoBuffer)
  203.                     strcpy(Work -> StringInfo -> UndoBuffer,Work -> PrevBuffer);
  204.  
  205.                 Work -> StringInfo -> UndoPos = Work -> BufferPos;
  206.  
  207.                 Work -> BufferPos    += Len;
  208.                 Work -> NumChars    += Len;
  209.  
  210.                 Work -> Actions = (Work -> Actions & ~SGA_BEEP) | SGA_USE | SGA_REDISPLAY;
  211.             }
  212.  
  213.             Permit();
  214.  
  215.             return(TRUE);
  216.         }
  217.  
  218.             /* The user pressed the cursor-right key to
  219.              * move the cursor to the next word in the buffer.
  220.              */
  221.  
  222.         if(Work -> IEvent -> ie_Code == CURSORRIGHT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
  223.         {
  224.             if(Work -> BufferPos != Work -> NumChars)
  225.             {
  226.                 LONG i,Position = -1;
  227.  
  228.                 for(i = Work -> BufferPos ; i < Work -> NumChars ; i++)
  229.                 {
  230.                     if(Work -> WorkBuffer[i] == ' ')
  231.                     {
  232.                         for( ; i < Work -> NumChars ; i++)
  233.                         {
  234.                             if(Work -> WorkBuffer[i] != ' ')
  235.                             {
  236.                                 Position = i;
  237.                                 break;
  238.                             }
  239.                         }
  240.  
  241.                         break;
  242.                     }
  243.                 }
  244.  
  245.                 if(Position != -1)
  246.                     Work -> BufferPos = Position;
  247.                 else
  248.                     Work -> BufferPos = Work -> NumChars;
  249.  
  250.                 Work -> EditOp = EO_MOVECURSOR;
  251.             }
  252.  
  253.             return(TRUE);
  254.         }
  255.  
  256.             /* The user pressed the cursor-right key to
  257.              * move the cursor to the previous word in the buffer.
  258.              */
  259.  
  260.         if(Work -> IEvent -> ie_Code == CURSORLEFT && (Work -> IEvent -> ie_Qualifier & IEQUALIFIER_CONTROL))
  261.         {
  262.             if(Work -> BufferPos)
  263.             {
  264.                 LONG i,Position = -1;
  265.  
  266.                 for(i = Work -> BufferPos ; i >= 0 ; i--)
  267.                 {
  268.                     if(Work -> WorkBuffer[i] != ' ')
  269.                     {
  270.                         Position = i;
  271.                         break;
  272.                     }
  273.                 }
  274.  
  275.                 if(Position == -1)
  276.                     Position = 0;
  277.  
  278.                 if(Position)
  279.                 {
  280.                     i = Position;
  281.  
  282.                     Position = -1;
  283.  
  284.                     for( ; i >= 0 ; i--)
  285.                     {
  286.                         if(Work -> WorkBuffer[i] == ' ')
  287.                         {
  288.                             Position = i + 1;
  289.                             break;
  290.                         }
  291.                     }
  292.                 }
  293.  
  294.                 if(Position != -1)
  295.                     Work -> BufferPos = Position;
  296.                 else
  297.                     Work -> BufferPos = 0;
  298.  
  299.                 Work -> EditOp = EO_MOVECURSOR;
  300.             }
  301.         }
  302.  
  303.             /* The user pressed the cursor-up key to
  304.              * scroll through the command history.
  305.              */
  306.  
  307.         if(Work -> IEvent -> ie_Code == CURSORUP)
  308.         {
  309.                 /* Shift key: jump to first command
  310.                  * history entry.
  311.                  */
  312.  
  313.             if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  314.             {
  315.                 if(PacketLine)
  316.                     SendPacketMsg(0);
  317.             }
  318.             else
  319.             {
  320.                 if(PacketLine && PacketCount > 0)
  321.                     SendPacketMsg(PacketCount - 1);
  322.             }
  323.         }
  324.  
  325.             /* The user pressed the cursor-down key to
  326.              * scroll through the command history.
  327.              */
  328.  
  329.         if(Work -> IEvent -> ie_Code == CURSORDOWN)
  330.         {
  331.                 /* Shift key: jump to last command
  332.                  * history entry.
  333.                  */
  334.  
  335.             if(Work -> IEvent -> ie_Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  336.             {
  337.                 if(PacketLine > 0)
  338.                     SendPacketMsg(PacketLine);
  339.             }
  340.             else
  341.             {
  342.                 if(PacketCount < PacketLine)
  343.                     SendPacketMsg(PacketCount + 1);
  344.             }
  345.         }
  346.  
  347.         return(TRUE);
  348.     }
  349.     else
  350.     {
  351.         if(*Msg == SGH_CLICK)
  352.             return(TRUE);
  353.         else
  354.             return(FALSE);
  355.     }
  356. }
  357.  
  358.     /* CreateAllGadgets():
  359.      *
  360.      *    Create the packet string gadget.
  361.      */
  362.  
  363. STATIC struct Gadget *
  364. CreateAllGadgets(LONG Width,struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo)
  365. {
  366.     STATIC struct Hook PacketHook =
  367.     {
  368.         {NULL},
  369.         (HOOKFUNC)PacketKey
  370.     };
  371.  
  372.     struct Gadget        *Gadget;
  373.     struct NewGadget     NewGadget;
  374.  
  375.     ObtainSemaphore(&PacketSemaphore);
  376.  
  377.     memset(&NewGadget,0,sizeof(struct NewGadget));
  378.  
  379.     if(Gadget = CreateContext(GadgetList))
  380.     {
  381.         LONG Rest,StringHeight,ProtoHeight;
  382.  
  383.         StringHeight    = 3 + TextAttr . tta_YSize + 3;
  384.         ProtoHeight    = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + StringHeight + 1 + Window -> WScreen -> WBorBottom;
  385.         Rest        = (PacketHeight - 2 - ProtoHeight - 2) / TextAttr . tta_YSize;
  386.  
  387.         NewGadget . ng_Width        = Width - 26;
  388.         NewGadget . ng_Height        = StringHeight;
  389.         NewGadget . ng_GadgetText    = NULL;
  390.         NewGadget . ng_TextAttr        = &TextAttr;
  391.         NewGadget . ng_VisualInfo    = VisualInfo;
  392.         NewGadget . ng_GadgetID        = GAD_STRING;
  393.         NewGadget . ng_Flags        = 0;
  394.         NewGadget . ng_LeftEdge        = 6;
  395.         NewGadget . ng_TopEdge        = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 2;
  396.  
  397.         GadgetArray[GAD_STRING] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  398.             GTST_MaxChars,    1024,
  399.             GTST_EditHook,    &PacketHook,
  400.             GA_TabCycle,    FALSE,
  401.         TAG_DONE);
  402.  
  403.             /* If the window is large enough to display the
  404.              * list, create the list view gadget.
  405.              */
  406.  
  407.         if(Rest > 0)
  408.         {
  409.             NewGadget . ng_Height        = 2 + Rest * TextAttr . tta_YSize + 2 + StringHeight;
  410.             NewGadget . ng_GadgetID        = GAD_LIST;
  411.  
  412.             GadgetArray[GAD_LIST] = Gadget = CreateGadget(LISTVIEW_KIND,Gadget,&NewGadget,
  413.                 GTLV_ShowSelected,    GadgetArray[GAD_STRING],
  414.                 GTLV_Labels,        &PacketHistoryList,
  415.                 GTLV_Selected,        PacketCount,
  416.                 GTLV_Top,        PacketCount,
  417.             TAG_DONE);
  418.  
  419.             if(Gadget)
  420.                 HasList = TRUE;
  421.             else
  422.                 HasList = FALSE;
  423.         }
  424.         else
  425.             HasList = FALSE;
  426.     }
  427.  
  428.     ReleaseSemaphore(&PacketSemaphore);
  429.  
  430.     return(Gadget);
  431. }
  432.  
  433.     /* HandlePacket():
  434.      *
  435.      *    Process the input coming through the packet window.
  436.      */
  437.  
  438. STATIC BOOL
  439. HandlePacket(VOID)
  440. {
  441.     struct IntuiMessage    *Message;
  442.     struct PacketMessage    *PacketMsg;
  443.     ULONG             MsgClass,MsgCode;
  444.     struct Gadget        *MsgGadget;
  445.     struct FileRequester    *FileRequest;
  446.     UBYTE             DummyBuffer[MAX_FILENAME_LENGTH];
  447.     BOOL             SwapWindow = FALSE;
  448.  
  449.     FOREVER
  450.     {
  451.         if(Wait(PORTMASK(PacketWindow -> UserPort) | SIG_KILL) & SIG_KILL)
  452.             return(TRUE);
  453.  
  454.         while(Message = (struct IntuiMessage *)GT_GetIMsg(PacketWindow -> UserPort))
  455.         {
  456.             MsgClass    = Message -> Class;
  457.             MsgCode        = Message -> Code;
  458.             MsgGadget    = (struct Gadget *)Message -> IAddress;
  459.  
  460.             GT_ReplyIMsg(Message);
  461.  
  462.                 /* Re-enable the string gadget if necessary. */
  463.  
  464.             if(MsgClass == IDCMP_RAWKEY)
  465.             {
  466.                 if(MsgCode == IECODE_UP_PREFIX|RAMIGA_CODE && CommandWindow == PacketWindow)
  467.                     ActivateGadget(CommandGadget,PacketWindow,NULL);
  468.  
  469.                 if(MsgCode == HELP_CODE)
  470.                     GuideDisplay(CONTEXT_PACKETWINDOW);
  471.             }
  472.  
  473.                 /* Menu help is required. */
  474.  
  475.             if(MsgClass == IDCMP_MENUHELP)
  476.                 GuideDisplay(CONTEXT_PACKET_MENU);
  477.  
  478.                 // Imagery may need refreshing
  479.  
  480.             if(MsgClass == IDCMP_REFRESHWINDOW)
  481.             {
  482.                 GT_BeginRefresh(PacketWindow);
  483.                 GT_EndRefresh(PacketWindow,TRUE);
  484.             }
  485.  
  486.                 /* Handle the menu. */
  487.  
  488.             if(MsgClass == IDCMP_MENUPICK)
  489.             {
  490.                 struct MenuItem *MenuItem;
  491.  
  492.                 while(MsgCode != MENUNULL)
  493.                 {
  494.                     MenuItem = ItemAddress(PacketMenu,MsgCode);
  495.  
  496.                     switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  497.                     {
  498.                         case MEN_TOGGLE_ECHO:
  499.  
  500.                             if(MenuItem -> Flags & CHECKED)
  501.                                 Echo = TRUE;
  502.                             else
  503.                                 Echo = FALSE;
  504.  
  505.                             break;
  506.  
  507.                         case MEN_QUITPANEL:
  508.  
  509.                             MsgClass = IDCMP_CLOSEWINDOW;
  510.                             break;
  511.  
  512.                         case MEN_LOADHISTORY:
  513.  
  514.                             LT_LockWindow(PacketWindow);
  515.  
  516.                             if(FileRequest = GetFile(PacketWindow,LocaleString(MSG_PACKET_LOAD_HISTORY_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT),FALSE))
  517.                             {
  518.                                 if(GetFileSize(DummyBuffer))
  519.                                 {
  520.                                     BPTR SomeFile;
  521.  
  522.                                     if(SomeFile = Open(DummyBuffer,MODE_OLDFILE))
  523.                                     {
  524.                                         if(PacketLine)
  525.                                         {
  526.                                             switch(ShowRequest(PacketWindow,LocaleString(MSG_PACKET_PACKET_WINDOW_STILL_HOLDS_LINES_TXT),LocaleString(MSG_PACKET_DISCARD_APPEND_CANCEL_TXT),PacketLine))
  527.                                             {
  528.                                                 case 1:    ClearPacketHistory();
  529.                                                     break;
  530.  
  531.                                                 case 0:    Close(SomeFile);
  532.                                                     SomeFile = NULL;
  533.                                                     break;
  534.                                             }
  535.                                         }
  536.  
  537.                                         if(SomeFile)
  538.                                         {
  539.                                             LONG Len;
  540.  
  541.                                             LineRead(NULL,NULL,NULL);
  542.  
  543.                                             while(Len = LineRead(SomeFile,DummyBuffer,255))
  544.                                             {
  545.                                                 DummyBuffer[Len - 1] = 0;
  546.  
  547.                                                 AddPacketHistory(DummyBuffer);
  548.                                             }
  549.  
  550.                                             Close(SomeFile);
  551.                                         }
  552.                                     }
  553.                                     else
  554.                                         ShowError(PacketWindow,ERR_LOAD_ERROR,IoErr(),DummyBuffer);
  555.                                 }
  556.  
  557.                                 FreeAslRequest(FileRequest);
  558.                             }
  559.  
  560.                             LT_UnlockWindow(PacketWindow);
  561.                             break;
  562.  
  563.                         case MEN_SAVEHISTORY:
  564.  
  565.                             LT_LockWindow(PacketWindow);
  566.  
  567.                             if(!PacketLine)
  568.                                 ShowRequest(PacketWindow,LocaleString(MSG_PACKET_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  569.                             else
  570.                             {
  571.                                 if(FileRequest = GetFile(PacketWindow,LocaleString(MSG_PACKET_SAVE_HISTORY_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT),FALSE))
  572.                                 {
  573.                                     BPTR SomeFile = NULL;
  574.                                     LONG Error = 0;
  575.  
  576.                                         /* If the file we are about
  577.                                          * to create already exists,
  578.                                          * ask the user whether we are
  579.                                          * to create, append or skip
  580.                                          * the file.
  581.                                          */
  582.  
  583.                                     if(GetFileSize(DummyBuffer))
  584.                                     {
  585.                                         switch(ShowRequest(PacketWindow,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),DummyBuffer))
  586.                                         {
  587.                                             case 1:    SomeFile = Open(DummyBuffer,MODE_NEWFILE);
  588.                                                 break;
  589.  
  590.                                             case 2:    if(SomeFile = Open(DummyBuffer,MODE_READWRITE))
  591.                                                 {
  592.                                                     if(Seek(SomeFile,0,OFFSET_END) == -1)
  593.                                                     {
  594.                                                         Close(SomeFile);
  595.  
  596.                                                         SomeFile = NULL;
  597.                                                     }
  598.                                                 }
  599.                                                 break;
  600.                                         }
  601.                                     }
  602.                                     else
  603.                                         SomeFile = Open(DummyBuffer,MODE_NEWFILE);
  604.  
  605.                                     if(!SomeFile)
  606.                                         Error = IoErr();
  607.                                     else
  608.                                     {
  609.                                         struct Node *SomeNode;
  610.  
  611.                                         ObtainSemaphore(&PacketSemaphore);
  612.  
  613.                                         SomeNode = PacketHistoryList . lh_Head;
  614.  
  615.                                         while(SomeNode -> ln_Succ)
  616.                                         {
  617.                                             SetIoErr(0);
  618.  
  619.                                             if(FPrintf(SomeFile,"%s\n",SomeNode -> ln_Name) < 1)
  620.                                             {
  621.                                                 Error = IoErr();
  622.  
  623.                                                 break;
  624.                                             }
  625.  
  626.                                             SomeNode = SomeNode -> ln_Succ;
  627.                                         }
  628.  
  629.                                         Close(SomeFile);
  630.  
  631.                                         if(GetFileSize(DummyBuffer))
  632.                                         {
  633.                                             AddProtection(DummyBuffer,FIBF_EXECUTE);
  634.  
  635.                                             if(Config -> MiscConfig -> CreateIcons)
  636.                                                 AddIcon(DummyBuffer,FILETYPE_TEXT,TRUE);
  637.                                         }
  638.                                         else
  639.                                             DeleteFile(DummyBuffer);
  640.  
  641.                                         ReleaseSemaphore(&PacketSemaphore);
  642.                                     }
  643.  
  644.                                     if(Error)
  645.                                         ShowError(PacketWindow,ERR_SAVE_ERROR,Error,DummyBuffer);
  646.  
  647.                                     FreeAslRequest(FileRequest);
  648.                                 }
  649.                             }
  650.  
  651.                             LT_UnlockWindow(PacketWindow);
  652.                             break;
  653.  
  654.                         case MEN_CLEARHISTORY:
  655.  
  656.                             LT_LockWindow(PacketWindow);
  657.  
  658.                             ClearPacketHistory();
  659.  
  660.                             LT_UnlockWindow(PacketWindow);
  661.                             break;
  662.  
  663.                         case MEN_OTHERWINDOW:
  664.  
  665.                             SwapWindow = TRUE;
  666.                             break;
  667.                     }
  668.  
  669.                     MsgCode = MenuItem -> NextSelect;
  670.                 }
  671.  
  672.                 ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  673.             }
  674.  
  675.                 /* Shut down. */
  676.  
  677.             if(MsgClass == IDCMP_CLOSEWINDOW)
  678.             {
  679.                 Forbid();
  680.  
  681.                 if(!(SetSignal(0,SIG_KILL) & SIG_KILL))
  682.                     return(FALSE);
  683.                 else
  684.                     return(TRUE);
  685.             }
  686.  
  687.                 /* Activate the string gadget as well. */
  688.  
  689.             if(MsgClass == IDCMP_ACTIVEWINDOW)
  690.                 ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  691.  
  692.             if(MsgClass == IDCMP_NEWSIZE)
  693.             {
  694.                 PacketWindow -> Flags |= WFLG_RMBTRAP;
  695.  
  696.                 strcpy(DummyBuffer,PacketContents);
  697.  
  698.                 RemoveGList(PacketWindow,PacketGadgetList,(UWORD)-1);
  699.  
  700.                 FreeGadgets(PacketGadgetList);
  701.  
  702.                 PacketGadgetList = NULL;
  703.  
  704.                 EraseWindow(PacketWindow,NULL);
  705.                 RefreshWindowFrame(PacketWindow);
  706.  
  707.                 PacketHeight    = PacketWindow -> Height;
  708.                 PacketWidth    = PacketWindow -> Width;
  709.  
  710.                 ObtainSemaphore(&PacketSemaphore);
  711.  
  712.                 if(CreateAllGadgets(PacketWindow -> Width,PacketGadgetArray,&PacketGadgetList,VisualInfo))
  713.                 {
  714.                     PacketContents = ((struct StringInfo *)PacketGadgetArray[GAD_STRING] -> SpecialInfo) -> Buffer;
  715.  
  716.                     AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
  717.                     RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
  718.                     GT_RefreshWindow(PacketWindow,NULL);
  719.  
  720.                     ReleaseSemaphore(&PacketSemaphore);
  721.  
  722.                     PacketWindow -> Flags &= ~WFLG_RMBTRAP;
  723.  
  724.                     GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  725.                         GTST_String,    DummyBuffer,
  726.                     TAG_DONE);
  727.  
  728.                     ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  729.                 }
  730.                 else
  731.                 {
  732.                     DisplayBeep(PacketWindow -> WScreen);
  733.  
  734.                     ReleaseSemaphore(&PacketSemaphore);
  735.  
  736.                     if(!(SetSignal(0,SIG_KILL) & SIG_KILL))
  737.                         return(FALSE);
  738.                     else
  739.                         return(TRUE);
  740.                 }
  741.             }
  742.  
  743.             if(MsgClass == IDCMP_MOUSEBUTTONS)
  744.                 ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  745.  
  746.                 /* User has entered a string. */
  747.  
  748.             if(MsgClass == IDCMP_GADGETUP)
  749.             {
  750.                 switch(MsgGadget -> GadgetID)
  751.                 {
  752.                     case GAD_STRING:
  753.  
  754.                         if(MsgCode != '\t')
  755.                         {
  756.                                 /* Is there anything in the buffer at all? */
  757.  
  758.                             if(PacketContents[0])
  759.                             {
  760.                                 strcpy(DummyBuffer,PacketContents);
  761.  
  762.                                 if(PacketString)
  763.                                 {
  764.                                     if(strcmp(PacketString,DummyBuffer))
  765.                                         AddPacketHistory(DummyBuffer);
  766.  
  767.                                     PacketString = NULL;
  768.                                 }
  769.                                 else
  770.                                     AddPacketHistory(DummyBuffer);
  771.  
  772.                                     /* Convert alien IBM characters. */
  773.  
  774.                                 if(Config -> TerminalConfig -> FontMode == FONT_IBM)
  775.                                 {
  776.                                     UBYTE Char;
  777.                                     LONG i;
  778.  
  779.                                     for(i = 0 ; i < strlen(DummyBuffer) ; i++)
  780.                                     {
  781.                                         if(Char = IBMConversion[DummyBuffer[i]])
  782.                                             DummyBuffer[i] = Char;
  783.                                     }
  784.                                 }
  785.  
  786.                                     /* Execute the command. */
  787.  
  788.                                 PacketSerialCommand(DummyBuffer);
  789.                             }
  790.  
  791.                                 /* Clear the packet window string
  792.                                  * gadget.
  793.                                  */
  794.  
  795.                             GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  796.                                 GTST_String,    "",
  797.                             TAG_DONE);
  798.  
  799.                                 /* Send a terminating `CR'. */
  800.  
  801.                             switch(Config -> TerminalConfig -> SendCR)
  802.                             {
  803.                                 case EOL_CR:
  804.  
  805.                                     PacketSerWrite("\r",1);
  806.                                     break;
  807.  
  808.                                 case EOL_LF:
  809.  
  810.                                     PacketSerWrite("\n",1);
  811.                                     break;
  812.  
  813.                                 case EOL_CRLF:
  814.  
  815.                                     PacketSerWrite("\r\n",2);
  816.                                     break;
  817.  
  818.                                 case EOL_LFCR:
  819.  
  820.                                     PacketSerWrite("\n\r",2);
  821.                                     break;
  822.                             }
  823.  
  824.                                 /* Re-activate the string gadget. */
  825.  
  826.                             ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  827.                         }
  828.  
  829.                         break;
  830.  
  831.                     case GAD_LIST:
  832.  
  833.                         ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  834.                         break;
  835.                 }
  836.             }
  837.  
  838.             if(SwapWindow)
  839.             {
  840.                 BumpWindow(Window);
  841.  
  842.                 SwapWindow = FALSE;
  843.             }
  844.         }
  845.  
  846.         if(PacketMsg = (struct PacketMessage *)GetMsg(PacketPort))
  847.         {
  848.             struct Node *Node;
  849.  
  850.             ObtainSemaphore(&PacketSemaphore);
  851.  
  852.             if(Node = GetListNode(PacketMsg -> Line,&PacketHistoryList))
  853.             {
  854.                 PacketString = Node -> ln_Name;
  855.  
  856.                 if(HasList)
  857.                 {
  858.                     GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  859.                         GTLV_Selected,    PacketMsg -> Line,
  860.                         GTLV_Top,    PacketMsg -> Line,
  861.                     TAG_DONE);
  862.                 }
  863.                 else
  864.                 {
  865.                     GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  866.                         GTST_String,    Node -> ln_Name,
  867.                     TAG_DONE);
  868.                 }
  869.             }
  870.             else
  871.             {
  872.                 PacketString = NULL;
  873.  
  874.                 GT_SetGadgetAttrs(PacketGadgetArray[GAD_STRING],PacketWindow,NULL,
  875.                     GTST_String,    "",
  876.                 TAG_DONE);
  877.             }
  878.  
  879.             ReleaseSemaphore(&PacketSemaphore);
  880.  
  881.             PacketCount = PacketMsg -> Line;
  882.  
  883.             FreeVecPooled(PacketMsg);
  884.  
  885.             ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  886.         }
  887.     }
  888. }
  889.  
  890. STATIC VOID __saveds
  891. PacketProcessEntry(VOID)
  892. {
  893.     BOOL RingBack = TRUE;
  894.  
  895.     if((PacketSignal = AllocSignal(-1)) != -1)
  896.     {
  897.         if(PacketPort = (struct MsgPort *)AllocVecPooled(sizeof(struct MsgPort),MEMF_PUBLIC | MEMF_CLEAR))
  898.         {
  899.             STATIC ULONG MenuTags[] =
  900.             {
  901.                 LAMN_TitleID,            MSG_PACKET_PROJECT_MEN,
  902.                     LAMN_ItemID,        MSG_PACKET_LOAD_HISTORY_MEN,
  903.                         LAMN_UserData,    MEN_LOADHISTORY,
  904.                     LAMN_ItemID,        MSG_PACKET_SAVE_HISTORY_MEN,
  905.                         LAMN_UserData,    MEN_SAVEHISTORY,
  906.                     LAMN_ItemID,        MSG_PACKET_CLEAR_HISTORY_MEN,
  907.                         LAMN_UserData,    MEN_CLEARHISTORY,
  908.  
  909.                     LAMN_ItemText,        (ULONG)NM_BARLABEL,
  910.  
  911.                     LAMN_ItemID,        MSG_PACKET_OTHER_WINDOW_MEN,
  912.                         LAMN_UserData,    MEN_OTHERWINDOW,
  913.  
  914.                     LAMN_ItemText,        (ULONG)NM_BARLABEL,
  915.  
  916.                     LAMN_ItemID,        MSG_PACKET_TOGGLE_ECHO_MEN,
  917.                         LAMN_UserData,    MEN_TOGGLE_ECHO,
  918.                         LAMN_Toggle,    TRUE,
  919.  
  920.                     LAMN_ItemText,        (ULONG)NM_BARLABEL,
  921.  
  922.                     LAMN_ItemID,        MSG_PACKET_QUIT_MEN,
  923.                         LAMN_UserData,    MEN_QUITPANEL,
  924.  
  925.                 TAG_DONE
  926.             };
  927.  
  928.             struct Message *Message;
  929.  
  930.             if(PacketMenu = LT_NewMenuTags(
  931.                 LAHN_LocaleHook,    &LocaleHook,
  932.                 LAMN_Screen,        Window -> WScreen,
  933.                 LAMN_TextAttr,        Window -> WScreen -> Font,
  934.                 LAMN_AmigaGlyph,    AmigaGlyph,
  935.                 LAMN_CheckmarkGlyph,    CheckGlyph,
  936.             TAG_MORE,MenuTags))
  937.             {
  938.                 LONG ProtoHeight;
  939.  
  940.                 ProtoHeight = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + 3 + TextAttr . tta_YSize + 3 + 1 + Window -> WScreen -> WBorBottom;
  941.  
  942.                 if(PacketWidth == -1)
  943.                     PacketWidth = Window -> Width;
  944.  
  945.                 if(PacketHeight < ProtoHeight)
  946.                     PacketHeight = ProtoHeight;
  947.  
  948.                 if(PacketX == -1 || (PacketX + PacketWidth > Window -> WScreen -> Width))
  949.                 {
  950.                     PacketX = Window -> LeftEdge;
  951.  
  952.                     if(PacketX + PacketWidth > Window -> WScreen -> Width)
  953.                         PacketWidth = Window -> WScreen -> Width - PacketX;
  954.                 }
  955.  
  956.                 if(PacketY == -1 || (PacketY + PacketHeight > Window -> WScreen -> Height))
  957.                 {
  958.                     PacketY = Window -> TopEdge + Window -> Height;
  959.  
  960.                     if(PacketY + PacketHeight > Window -> WScreen -> Height)
  961.                         PacketHeight = ProtoHeight;
  962.                 }
  963.  
  964.                 if(CreateAllGadgets(PacketWidth,PacketGadgetArray,&PacketGadgetList,VisualInfo))
  965.                 {
  966.                     if(PacketWindow = OpenWindowTags(NULL,
  967.                         WA_Width,        PacketWidth,
  968.                         WA_Height,        PacketHeight,
  969.  
  970.                         WA_Left,        PacketX,
  971.                         WA_Top,            PacketY,
  972.  
  973.                         WA_Activate,        TRUE,
  974.                         WA_DragBar,        TRUE,
  975.                         WA_DepthGadget,        TRUE,
  976.                         WA_CloseGadget,        TRUE,
  977.                         WA_RMBTrap,        TRUE,
  978.                         WA_SizeGadget,        TRUE,
  979.                         WA_MinWidth,        80,
  980.                         WA_MinHeight,        ProtoHeight,
  981.                         WA_MaxWidth,        Window -> WScreen -> Width,
  982.                         WA_MaxHeight,        Window -> WScreen -> Height,
  983.                         OpenWindowTag,        Window -> WScreen,
  984.                         WA_NewLookMenus,    TRUE,
  985.                         WA_SimpleRefresh,    TRUE,
  986.                         BackfillTag,        &BackfillHook,
  987.  
  988.                         WA_IDCMP,        STRINGIDCMP | LISTVIEWIDCMP | IDCMP_NEWSIZE | IDCMP_SIZEVERIFY | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK | IDCMP_ACTIVEWINDOW | IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_MENUHELP | IDCMP_REFRESHWINDOW,
  989.                         WA_MenuHelp,        TRUE,
  990.  
  991.                         WA_Title,        LocaleString(MSG_GLOBAL_PACKET_WINDOW_TXT),
  992.  
  993.                         AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  994.                         CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  995.                     TAG_DONE))
  996.                     {
  997.                         APTR OldPtr;
  998.  
  999.                         PacketPort -> mp_Flags        = PA_SIGNAL;
  1000.                         PacketPort -> mp_SigBit        = PacketWindow -> UserPort -> mp_SigBit;
  1001.                         PacketPort -> mp_SigTask    = PacketWindow -> UserPort -> mp_SigTask;
  1002.  
  1003.                         NewList(&PacketPort -> mp_MsgList);
  1004.  
  1005.                         PacketContents = ((struct StringInfo *)PacketGadgetArray[GAD_STRING] -> SpecialInfo) -> Buffer;
  1006.  
  1007.                         AddGList(PacketWindow,PacketGadgetList,(UWORD)-1,(UWORD)-1,NULL);
  1008.                         RefreshGList(PacketGadgetList,PacketWindow,NULL,(UWORD)-1);
  1009.                         GT_RefreshWindow(PacketWindow,NULL);
  1010.  
  1011.                         SetMenuStrip(PacketWindow,PacketMenu);
  1012.  
  1013.                         PacketWindow -> Flags &= ~WFLG_RMBTRAP;
  1014.  
  1015.                         ActivateGadget(PacketGadgetArray[GAD_STRING],PacketWindow,NULL);
  1016.  
  1017.                         PacketProcess = (struct Process *)FindTask(NULL);
  1018.  
  1019.                         OldPtr = PacketProcess -> pr_WindowPtr;
  1020.  
  1021.                         PacketProcess -> pr_WindowPtr = PacketWindow;
  1022.  
  1023.                         Signal(ThisProcess,SIG_HANDSHAKE);
  1024.  
  1025.                         RingBack = HandlePacket();
  1026.  
  1027.                         PacketProcess -> pr_WindowPtr = OldPtr;
  1028.  
  1029.                         PacketWindow -> Flags |= WFLG_RMBTRAP;
  1030.  
  1031.                         ClearMenuStrip(PacketWindow);
  1032.  
  1033.                         RemoveGList(PacketWindow,PacketGadgetList,(UWORD)-1);
  1034.  
  1035.                         PacketX        = PacketWindow -> LeftEdge;
  1036.                         PacketY        = PacketWindow -> TopEdge;
  1037.  
  1038.                         PacketWidth    = PacketWindow -> Width;
  1039.                         PacketHeight    = PacketWindow -> Height;
  1040.  
  1041.                         LT_DeleteWindowLock(PacketWindow);
  1042.  
  1043.                         CloseWindow(PacketWindow);
  1044.                         PacketWindow = NULL;
  1045.                     }
  1046.  
  1047.                     FreeGadgets(PacketGadgetList);
  1048.                     PacketGadgetList = NULL;
  1049.                 }
  1050.  
  1051.                 LT_DisposeMenu(PacketMenu);
  1052.                 PacketMenu = NULL;
  1053.             }
  1054.  
  1055.             while(Message = GetMsg(PacketPort))
  1056.                 FreeVecPooled(Message);
  1057.  
  1058.             FreeVecPooled(PacketPort);
  1059.             PacketPort = NULL;
  1060.         }
  1061.  
  1062.         FreeSignal(PacketSignal);
  1063.         PacketSignal = -1;
  1064.     }
  1065.  
  1066.     Forbid();
  1067.  
  1068.     PacketProcess = NULL;
  1069.  
  1070.     if(RingBack)
  1071.         Signal(ThisProcess,SIG_HANDSHAKE);
  1072.     else
  1073.         CheckItem(MEN_PACKET_WINDOW,FALSE);
  1074. }
  1075.  
  1076.     /* ClearPacketHistory():
  1077.      *
  1078.      *    Release the command history.
  1079.      */
  1080.  
  1081. VOID
  1082. ClearPacketHistory()
  1083. {
  1084.     if(PacketProcess)
  1085.     {
  1086.         ObtainSemaphore(&PacketSemaphore);
  1087.  
  1088.         if(HasList)
  1089.         {
  1090.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1091.                 GTLV_Labels,~0,
  1092.             TAG_DONE);
  1093.         }
  1094.  
  1095.         FreeList(&PacketHistoryList);
  1096.  
  1097.         PacketCount = PacketLine = 0;
  1098.  
  1099.         if(HasList)
  1100.         {
  1101.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1102.                 GTLV_Labels,&PacketHistoryList,
  1103.             TAG_DONE);
  1104.         }
  1105.  
  1106.         PacketString = NULL;
  1107.  
  1108.         ReleaseSemaphore(&PacketSemaphore);
  1109.     }
  1110. }
  1111.  
  1112.     /* AddPacketHistory(STRPTR Buffer):
  1113.      *
  1114.      *    Add a line to the packet window command history. This
  1115.      *    works very much the same as the AddLine()-routine.
  1116.      */
  1117.  
  1118. VOID
  1119. AddPacketHistory(STRPTR Buffer)
  1120. {
  1121.     if(PacketProcess)
  1122.     {
  1123.         struct Node *SomeNode;
  1124.  
  1125.         ObtainSemaphore(&PacketSemaphore);
  1126.  
  1127.         if(HasList)
  1128.         {
  1129.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1130.                 GTLV_Labels,    ~0,
  1131.             TAG_DONE);
  1132.         }
  1133.  
  1134.         if(SomeNode = CreateNode(Buffer))
  1135.         {
  1136.             AddTail(&PacketHistoryList,SomeNode);
  1137.  
  1138.             PacketCount = ++PacketLine;
  1139.         }
  1140.  
  1141.         if(HasList)
  1142.         {
  1143.             GT_SetGadgetAttrs(PacketGadgetArray[GAD_LIST],PacketWindow,NULL,
  1144.                 GTLV_Top,    PacketCount - 1,
  1145.                 GTLV_Labels,    &PacketHistoryList,
  1146.             TAG_DONE);
  1147.         }
  1148.  
  1149.         ReleaseSemaphore(&PacketSemaphore);
  1150.     }
  1151. }
  1152.  
  1153.     /* DeletePacketWindow():
  1154.      *
  1155.      *    Delete the packet window and release the command
  1156.      *    history.
  1157.      */
  1158.  
  1159. VOID
  1160. DeletePacketWindow(BOOL WindowOnly)
  1161. {
  1162.     CheckItem(MEN_PACKET_WINDOW,FALSE);
  1163.  
  1164.     if(PacketProcess)
  1165.     {
  1166.         Forbid();
  1167.  
  1168.         ClrSignal(SIG_HANDSHAKE);
  1169.  
  1170.         Signal(PacketProcess,SIG_KILL);
  1171.  
  1172.         Wait(SIG_HANDSHAKE);
  1173.  
  1174.         Permit();
  1175.  
  1176.         if(!WindowOnly)
  1177.         {
  1178.             HasList = FALSE;
  1179.  
  1180.             FreeList(&PacketHistoryList);
  1181.  
  1182.             PacketCount = PacketLine = 0;
  1183.  
  1184.             PacketString = NULL;
  1185.         }
  1186.     }
  1187. }
  1188.  
  1189.     /* CreatePacketWindow():
  1190.      *
  1191.      *    Open the packet window and allocate the command history
  1192.      *    buffer.
  1193.      */
  1194.  
  1195. BOOL
  1196. CreatePacketWindow()
  1197. {
  1198.     if(Echo == -1)
  1199.         Echo = Config -> SerialConfig -> Duplex;
  1200.  
  1201.     if(!PacketProcess)
  1202.     {
  1203.         InitSemaphore(&PacketSemaphore);
  1204.  
  1205.         Forbid();
  1206.  
  1207.         if(CreateNewProcTags(
  1208.             NP_Name,    "term Packet Process",
  1209.             NP_Entry,    PacketProcessEntry,
  1210.         TAG_DONE))
  1211.         {
  1212.             ClrSignal(SIG_HANDSHAKE);
  1213.  
  1214.             Wait(SIG_HANDSHAKE);
  1215.         }
  1216.  
  1217.         Permit();
  1218.     }
  1219.  
  1220.     if(PacketProcess)
  1221.     {
  1222.         Forbid();
  1223.  
  1224.         ActivateWindow(PacketWindow);
  1225.  
  1226.         CheckItem(MEN_PACKET_WINDOW,TRUE);
  1227.  
  1228.         Permit();
  1229.  
  1230.         return(TRUE);
  1231.     }
  1232.     else
  1233.     {
  1234.         CheckItem(MEN_PACKET_WINDOW,FALSE);
  1235.  
  1236.         return(FALSE);
  1237.     }
  1238. }
  1239.